﻿/*****************************************介绍*****************************************
 * 作者：Ywh
 * 创建时间：2024-05-25 17:44:49
 * 功能：事件中心
 *      1、添加
 *      2、移除事件
 *      3、派发事件
 *      4、最多支持10个参数
**************************************************************************************/

using System;
using System.Collections.Generic;

namespace Game.Framework
{
    [InternalModule(1)]
    public class EventCenter : BaseManager<EventCenter>, IModule
    {
        private Dictionary<string, Delegate> m_EventDict;

        private EventCenter() { }

        #region 添加事件

        private void AddEventListen_Internal(string eventName, Delegate handle)
        {
            if (string.IsNullOrWhiteSpace(eventName))
            {
                LogManager.LogError($"事件名不能为空！！", "EventCenter", "AddEvent");
                return;
            }

            if (m_EventDict.TryGetValue(eventName, out var handleInternal))
            {
                try
                {
                    m_EventDict[eventName] = Delegate.Combine(handleInternal, handle);
                }
                catch (ArgumentException)
                {
                    LogManager.LogError($"相同的事件不能使用不同类型的函数，eventName:{eventName} targetFunc:{handle.Method.Name}", "EventCenter", "AddEvent");
                }
            }
            else
                m_EventDict.Add(eventName, handle);
        }

        public void AddEventListen(string eventName, Action handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T>(string eventName, Action<T> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2>(string eventName, Action<T1, T2> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3>(string eventName, Action<T1, T2, T3> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4>(string eventName, Action<T1, T2, T3, T4> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4, T5>(string eventName, Action<T1, T2, T3, T4, T5> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4, T5, T6>(string eventName, Action<T1, T2, T3, T4, T5, T6> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4, T5, T6, T7>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4, T5, T6, T7, T8>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7, T8> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4, T5, T6, T7, T8, T9>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> handle) => AddEventListen_Internal(eventName, handle);
        public void AddEventListen<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> handle) => AddEventListen_Internal(eventName, handle);

        #endregion

        #region 移除事件

        private void RemoveEventListen_Internal(string eventName, Delegate handle)
        {
            if (!string.IsNullOrWhiteSpace(eventName) && m_EventDict != null && m_EventDict.TryGetValue(eventName, out var handleInternanl))
                m_EventDict[eventName] = Delegate.Remove(handleInternanl, handle);
        }
        public void RemoveEventListen(string eventName, Action handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T>(string eventName, Action<T> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2>(string eventName, Action<T1, T2> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3>(string eventName, Action<T1, T2, T3> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4>(string eventName, Action<T1, T2, T3, T4> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4, T5>(string eventName, Action<T1, T2, T3, T4, T5> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4, T5, T6>(string eventName, Action<T1, T2, T3, T4, T5, T6> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4, T5, T6, T7>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4, T5, T6, T7, T8>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7, T8> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4, T5, T6, T7, T8, T9>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> handle) => RemoveEventListen_Internal(eventName, handle);
        public void RemoveEventListen<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(string eventName, Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> handle) => RemoveEventListen_Internal(eventName, handle);

        #endregion

        #region 触发事件

        private bool Trigger_Internal(string eventName, out Delegate handle, out string error)
        {
            error = "";
            handle = null;
            if (string.IsNullOrWhiteSpace(eventName) || !m_EventDict.TryGetValue(eventName, out handle))
            {
                error = $"不存在的事件，type:{eventName}";
                return false;
            }
            return true;
        }
        public string Trigger(string eventName)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action;
                action?.Invoke();
            }
            return error;
        }
        public string Trigger<T>(string eventName, T value)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T>;
                action?.Invoke(value);
            }
            return error;
        }
        public string Trigger<T1, T2>(string eventName, T1 v1, T2 v2)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2>;
                action?.Invoke(v1, v2);
            }
            return error;
        }
        public string Trigger<T1, T2, T3>(string eventName, T1 v1, T2 v2, T3 v3)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3>;
                action?.Invoke(v1, v2, v3);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4>;
                action?.Invoke(v1, v2, v3, v4);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4, T5>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4, T5>;
                action?.Invoke(v1, v2, v3, v4, v5);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4, T5, T6>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4, T5, T6>;
                action?.Invoke(v1, v2, v3, v4, v5, v6);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4, T5, T6, T7>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4, T5, T6, T7>;
                action?.Invoke(v1, v2, v3, v4, v5, v6, v7);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4, T5, T6, T7, T8>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4, T5, T6, T7, T8>;
                action?.Invoke(v1, v2, v3, v4, v5, v6, v7, v8);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4, T5, T6, T7, T8, T9>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4, T5, T6, T7, T8, T9>;
                action?.Invoke(v1, v2, v3, v4, v5, v6, v7, v8, v9);
            }
            return error;
        }
        public string Trigger<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(string eventName, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10)
        {
            if (Trigger_Internal(eventName, out var handle, out var error))
            {
                var action = handle as Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>;
                action?.Invoke(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10);
            }
            return error;
        }

        #endregion

        public void RemoveEventAllListen(string eventName)
        {
            if (m_EventDict.ContainsKey(eventName))
            {
                m_EventDict.Remove(eventName);
            }
        }

        private InitResult m_InitResult;

        void IModule.Init()
        {
            m_EventDict = new Dictionary<string, Delegate>();
            m_InitResult = new InitResult(E_ResultType.Success);
        }

        InitResult IModule.GetInitResult() => m_InitResult;

        void IModule.Clear()
        {
            m_EventDict.Clear();
            m_EventDict = null;
        }
    }
}